#define _CRT_SECURE_NO_WARNINGS 1


#pragma once

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define LINE_SIZE 1024
#define FLUSH_NOW  1            //立即刷新
#define FLUSH_LINE 2            //行刷新
#define FLUSH_FULL 4            //全刷新

struct myFILE
{
    unsigned int flags;     //标记位
    int fileno;             //文件描述符
    //缓冲区
    char cache[LINE_SIZE];  //行缓冲区
    int cap;                //缓冲区总容量
    int pos;                //下次写入的位置
};

//打开文件
myFILE* fp = my_fopen(const char* path, const char* flag)
{
    int flag1 = 0;
    int iscreate = 0;
    mode_t mode = 0666;
    if (strcmp(flag, "r") == 0)
    {
        flag1 = (O_RDONLY);
    }
    else if (strcmp(flag, "W") == 0)
    {
        flag1 = (O_WRONLY | O_CREAT | O_TRUNC);
        iscreate = 1;
    }
    else if (strcmp(flag, "a") == 0)
    {
        flag1 = (O_WRONLY | O_CREAT | O_APPEND);
        iscreate = 1;
    }
    else
    {
    }

    int fd = 0;
    if (iscreate)    //判断是否需要创建文件
    {
        fd = open(path, flag1, mode);   //打开的(文件， 方式， 权限)    
    }
    else
    {
        fd = open(path, flag1);
    }

    if (fd < 0) return NULL;                 //打开文件失败

    myFILE* fp = (myFILE*)malloc(sizeof(myFILE));
    if (!pf) return NULL;                    //扩容失败返回 NULL

    fp->fileno = fd;
    fp->flags = FLUSH_LINE;                //采用行刷新    

    fp->cap = LINE_SIZE;
    fp->pos = 0;                            //默认从头开始写        

    return fp;
}

//刷新缓冲区(行刷新)
void my_fflush(myFILE* fp)
{
    write(fp->fileno, fp->cache, fp->pos);
    fp->pos = 0;
}

//写入
ssize_t my_fwrite(myFILE* fp, const char* data, int len) //文件里写,写的数据,写多长
{
    //写入操作 本质是拷贝,如果条件允许就刷新，否则不刷新
    memcpy(fp->cache + fp->pos, data, len); //考虑越界，扩容
    fp->pos += len;                         //跟新数据数量
    if ((fp->flags & FLUSH_LINE) && fp->cache[fp->pos - 1] == '\n')
    {
        my_fflush(fp);
    }
    return len;
}


// 关闭文件
void my_fclose(fp)
{
    my_fflush(fp);
    close(fp->fileno);      //关闭文件描述符
    delete fp;              //释放空间
}


————————————————————————————————————————————————————————

 
————————————————————————————————————————————————————————


          《 模拟实现库 》


#include <stdio.h>
int fprintf(FILE* stream, const char* format, ...);


————————————————————————————————————————————————————————


————————————————————————————————————————————————————————


		《 Makefile 》

bin = testfile
src = mystdio.c testfile.c

$(bin) :$(src)
@gcc - o $@ $ ^
.PHONY:clean
clean :
@rm - f $(bin)

————————————————————————————————————————————————————————

		《 mystdio.h 》


pragma once

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define LINE_SIZE 1024
#define FLUSH_NOW  1            //立即刷新
#define FLUSH_LINE 2            //行刷新
#define FLUSH_FULL 4            //全刷新


struct _myFILE
{
    unsigned int flags;     //标记位
    int fileno;             //文件描述符
    //缓冲区
    char cache[LINE_SIZE];  //行缓冲区
    int cap;                //缓冲区总容量
    int pos;                //下次写入的位置
};
typedef struct _myFILE myFILE;  // C 语言用结构体前面要加 struct 

//打开文件
myFILE* my_fopen(const char* path, const char* flag);

//刷新缓冲区(行刷新)
void my_fflush(myFILE* fp);

//写入
ssize_t my_fwrite(myFILE* fp, const char* data, int len); //文件里写,写的数据,写多长

// 关闭文件
void my_fclose(myFILE* fp);


————————————————————————————————————————————————————————


      《 mystdio.c 》
    
include "mystdio.h"

//打开文件
myFILE* my_fopen(const char* path, const char* flag)
{
    int flag1 = 0;
    int iscreate = 0;
    mode_t mode = 0666;
    if (strcmp(flag, "r") == 0)
    {
        flag1 = (O_RDONLY);
    }
    else if (strcmp(flag, "w") == 0)
    {
        flag1 = (O_WRONLY | O_CREAT | O_TRUNC);
        iscreate = 1;
    }
    else if (strcmp(flag, "a") == 0)
    {
        flag1 = (O_WRONLY | O_CREAT | O_APPEND);
        iscreate = 1;
    }
    else
    {
    }

    int fd = 0;
    if (iscreate)    //判断是否需要创建文件
    {
        fd = open(path, flag1, mode);   //打开的(文件， 方式， 权限)    

    }
    else
    {
        fd = open(path, flag1);
    }

    if (fd < 0) return NULL;                 //打开文件失败

    myFILE* fp = (myFILE*)malloc(sizeof(myFILE));
    if (!fp) return NULL;                    //扩容失败返回 NULL

    fp->fileno = fd;
    fp->flags = FLUSH_LINE;                //采用行刷新    

    fp->cap = LINE_SIZE;
    fp->pos = 0;                            //默认从头开始写        

    return fp;
}

//刷新缓冲区(行刷新)
void my_fflush(myFILE* fp)
{
    write(fp->fileno, fp->cache, fp->pos);
    fp->pos = 0;
}

//写入
ssize_t my_fwrite(myFILE* fp, const char* data, int len) //文件里写,写的数据,写多长
{
    //写入操作 本质是拷贝,如果条件允许就刷新，否则不刷新
    memcpy(fp->cache + fp->pos, data, len); //考虑越界，扩容
    fp->pos += len;                         //跟新数据数量
    if ((fp->flags & FLUSH_LINE) && fp->cache[fp->pos - 1] == '\n')
    {
        my_fflush(fp);
    }
    return len;
}

// 关闭文件
void my_fclose(myFILE* fp)
{
    my_fflush(fp);
    close(fp->fileno);      //关闭文件描述符
    free(fp);              //释放空间
}


————————————————————————————————————————————————————————


      《 testfile.c 》

#include "mystdio.h"
#include <string.h>
#include <stdio.h>
#include <unistd.h>

#define FILE_NAME "log.txt"


int main()
{
    myFILE* fp = my_fopen(FILE_NAME, "w");  //以 'w' 的方式打开文件
    if (fp == NULL) return 1;                //打开失败返回 1

    const char* str = "hello bit";
    int cnt = 10;
    char buffer[128];
    //      while(cnt)
    //      {
    //
    //              my_fwrite(fp, str, strlen(str));// strlen()+1 不需要C的+1
    //              cnt--;
    //      }

            //有 无'\n' 刷新
    //      while(cnt)
    //      {
    //              //sprintf(buffer, "%s - %d\n", str, cnt);
    //              sprintf(buffer, "%s - %d", str, cnt);
    //              my_fwrite(fp, buffer, strlen(buffer));
    //              cnt--;
    //              sleep(1);
    //      }

            //没'\n'但  强制刷新 
    while (cnt)
    {
        sprintf(buffer, "%s - %d", str, cnt);
        my_fwrite(fp, buffer, strlen(buffer));
        cnt--;
        sleep(1);
        my_fflush(fp);
    }

    my_fclose(fp);
    return 0;
}

————————————————————————————————————————————————————————

运行结果：

带 '/n' 时，1S 刷新一行出来，	//与强制刷新效果一样 
hello bit - 10
hello bit - 9
hello bit - 8
	... ...

不带 '/n' 时，程序结束时才整体刷新 1次 缓冲区。 
[a@192 stdio]$ cat log.txt
[a@192 stdio]$ cat log.txt
[a@192 stdio]$ cat log.txt
hello bit - 10hello bit - 9hello bit - 8
   ... ...
hello bit - 2hello bit - 1[a@192 stdio]$


————————————————————————————————————————————————————————


————————————————————————————————————————————————————————

1.代码1 shell中加入重定向 -- 最后一个shell
进程的程序替换，会不会影响进程关联的或者打开的文件呢 ? ? ? 
：不会

2.封装一下简单库：
C语言为什么要在FILE中提供用户级缓冲区 …
为了减少底层调用系统调用的次数，
让使用C10函数(printh, fprintf)效率更高
